# from cProfile import label
import numpy as np
import matplotlib.pyplot as plt
# from regex import P


def function_f(x):
    return x ** 8 - 8 * x ** 7 + 28 * x**6 - 56 * x ** 5 + 70 * x ** 4 - 56 * x ** 3 + 28 * x ** 2 - 8 * x + 1


def function_g(x):
    return (((((((x - 8) * x + 28) * x - 56) * x + 70) * x - 56) * x + 28) * x - 8) * x + 1


def function_h(x):
    return (x - 1) ** 8


def problemA():
    x_values = np.linspace(0.99, 1.01, 101)
    y_values = np.linspace(0.99999, 1.00001, 21)

    f_x = function_f(x_values)
    g_x = function_g(x_values)
    h_x = function_h(x_values)

    f_y = function_f(y_values)
    g_y = function_g(y_values)
    h_y = function_h(y_values)

    magnified_scale = 1e+15

    plt.figure(figsize=(16, 9))

    plt.subplot(2, 2, 1)
    plt.plot(x_values, f_x, label='Function f')
    plt.title('Function f')

    plt.subplot(2, 2, 2)
    plt.plot(x_values, g_x, label='Function g')
    plt.title('Function g')

    plt.subplot(2, 2, 3)
    plt.plot(x_values, h_x, label='Function h')
    plt.title('Function h')

    plt.subplot(2, 2, 4)
    plt.plot(y_values, magnified_scale * f_y, label='Function f')
    plt.plot(y_values, magnified_scale * g_y, label='Function g')
    plt.plot(y_values, magnified_scale * h_y, label='Function h')
    plt.title('comparison near 1')
    plt.legend()
    plt.grid(True)

    plt.tight_layout()
    plt.show()


def problemB():
    # 浮点数系统的参数
    beta = 2
    p = 3
    L = -1
    U = +1

    # 计算上下界
    UFL = beta ** L
    OFL = beta ** U * (beta - beta**(1 - p))
    print(f"UFL = {UFL}, OFL = {OFL}")

    # 枚举规范化浮点数
    F = np.array([0])
    for sign in {-1, 1}:
        for n in range(L, U + 1):
            for i in range(0, beta):
                for j in range(0, beta):
                    fp = sign * (1 + i / 2 + j / 4) * 2 ** n
                    print(fp)
                    F = np.append(F, fp)

    # 验证F的基数为 2^p*(U − L + 1) + 1.
    print(f"#F = {np.size(F)}")

    # 画出规范化浮点数系统
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 9))
    # ax1.plot([-4, 4], [0, 0], color='black', linestyle='-', lw=2)
    ax1.annotate("", xy=(-4.0, 0), xytext=(4.0, 0),
                 arrowprops=dict(arrowstyle="<->", color='black', lw=2))
    for number in F:
        ax1.plot(number, 0, color='red', marker='+',
                 markersize=14, label=str(number))
    ax1.set_xlim(-4, 4)
    ax1.set_ylim(-0.5, 0.5)
    ax1.spines['right'].set_color('none')
    ax1.spines['left'].set_color('none')
    ax1.spines['top'].set_color('none')
    ax1.spines['bottom'].set_color('none')
    ax1.spines['bottom'].set_position(('data', 0))
    ax1.xaxis.set_ticks_position('none')
    ax1.set_yticks([])
    ax1.set_xlabel("Number Line")
    ax1.set_title("normalized FPN system")

    # 枚举次规范化浮点数
    for sign in {-1, 1}:
        for i in range(0, beta):
            for j in range(0, beta):
                if i == 0 and j == 0:
                    continue
                fp = sign * (i / 2 + j / 4) * 2 ** L
                print(fp)
                F = np.append(F, fp)

    # 画出扩展浮点数系统
    # ax2.plot([-4, 4], [0, 0], color='black', linestyle='-', lw=2)
    ax2.annotate("", xy=(-4, 0), xytext=(4, 0),
                 arrowprops=dict(arrowstyle="<->", color='black', lw=2))
    for number in F:
        ax2.plot(number, 0, color='red', marker='+',
                 markersize=14, label=str(number))
    ax2.set_xlim(-4, 4)
    ax2.set_ylim(-0.5, 0.5)
    ax2.spines['right'].set_color('none')
    ax2.spines['left'].set_color('none')
    ax2.spines['top'].set_color('none')
    ax2.spines['bottom'].set_color('none')
    ax2.spines['bottom'].set_position(('data', 0))
    ax2.xaxis.set_ticks_position('none')
    ax2.set_yticks([])
    ax2.set_xlabel("Number Line")
    ax2.set_title("extended FPN system")

    plt.subplots_adjust(hspace=0.5)
    plt.show()


problemA()

problemB()
